package com.alax.interfaces.service.impl;

import com.alax.interfaces.domain.dto.DashboardSummaryDTO;
import com.alax.interfaces.domain.dto.NameValueDTO;
import com.alax.interfaces.domain.dto.TimeSeriesDTO;
import com.alax.interfaces.domain.dto.RealtimeStatsDTO;
import com.alax.interfaces.domain.dto.TimePointStats;
import com.alax.interfaces.mapper.ApiInfoMapper; // 假设存在
import com.alax.interfaces.mapper.DashboardMapper; // 需要创建
import com.alax.interfaces.service.IDashboardService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class DashboardServiceImpl implements IDashboardService {

    private static final Logger log = LoggerFactory.getLogger(DashboardServiceImpl.class);

    @Autowired
    private DashboardMapper dashboardMapper;

    @Autowired
    private ApiInfoMapper apiInfoMapper; // 假设注入

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public DashboardSummaryDTO getDashboardSummary() {
        DashboardSummaryDTO summary = new DashboardSummaryDTO();

        // 1. 总API数 (需要ApiInfoMapper)
        try {
            // 假设 ApiInfoMapper 有 selectApiInfoCount 方法
            Long apiCount = apiInfoMapper.selectApiInfoCount(null); // 传入 null 或一个空的查询对象
            summary.setTotalApis(apiCount != null ? apiCount : 0L);
        } catch (Exception e) {
            // Log error, maybe set default value
            System.err.println("Error getting total API count: " + e.getMessage());
            summary.setTotalApis(0L); // 设置默认值或抛出异常
        }


        // 获取今天的开始和结束时间
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        // 2. 今日调用总数
        Long todayTotalCalls = dashboardMapper.countCallsBetween(todayStart, todayEnd);
        summary.setTodayCalls(todayTotalCalls != null ? todayTotalCalls : 0L);

        // 3. 今日活跃用户数 (去重用户ID)
        Long todayActiveUsers = dashboardMapper.countDistinctUsersBetween(todayStart, todayEnd);
        summary.setActiveUsers(todayActiveUsers != null ? todayActiveUsers : 0L);

        // 4. 今日错误率
        if (todayTotalCalls != null && todayTotalCalls > 0) {
            Long todayFailedCalls = dashboardMapper.countCallsWithStatusBetween(0, todayStart, todayEnd); // status 0 = 失败
            if (todayFailedCalls != null) {
                double rate = (double) todayFailedCalls / todayTotalCalls * 100.0;
                // 保留两位小数
                summary.setErrorRate(Math.round(rate * 100.0) / 100.0);
            } else {
                summary.setErrorRate(0.0);
            }
        } else {
            summary.setErrorRate(0.0);
        }

        return summary;
    }

    @Override
    public TimeSeriesDTO getCallsTrend(int days) {
        LocalDateTime end = LocalDateTime.now();
        LocalDateTime start = end.minusDays(days - 1).with(LocalTime.MIN); //包含今天，所以是 days-1

        List<Map<String, Object>> dailyCounts = dashboardMapper.getDailyCallCountsBetween(start, end);

        // 使用 Map 方便填充缺失日期
        Map<String, Long> countsMap = dailyCounts.stream()
                .collect(Collectors.toMap(
                        map -> ((java.sql.Date) map.get("call_date")).toLocalDate().format(DATE_FORMATTER), // Key 是日期字符串
                        map -> (Long) map.get("count") // Value 是次数
                ));

        TimeSeriesDTO timeSeries = new TimeSeriesDTO();
        List<String> dates = new ArrayList<>();
        List<Long> counts = new ArrayList<>();

        // 生成最近 N 天的日期列表，并从 Map 中获取数据，没有则补0
        IntStream.range(0, days).mapToObj(i -> start.toLocalDate().plusDays(i)).forEach(date -> {
            String dateStr = date.format(DATE_FORMATTER);
            dates.add(dateStr);
            counts.add(countsMap.getOrDefault(dateStr, 0L));
        });

        timeSeries.setDates(dates);
        timeSeries.setCounts(counts);
        return timeSeries;
    }

    @Override
    public List<NameValueDTO> getStatusDistribution(String period) {
        LocalDateTime start;
        LocalDateTime end = LocalDateTime.now();

        // 定义时间段逻辑 (可以扩展更多 period)
        switch (period.toLowerCase()) {
            case "last7days":
                start = end.minusDays(7).with(LocalTime.MIN);
                break;
            case "today":
            default: // 默认为今天
                start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
                break;
        }

        List<Map<String, Object>> statusCounts = dashboardMapper.getCallStatusCountsBetween(start, end);

        // 转换为 NameValueDTO 列表
        return statusCounts.stream().map(map -> {
            Integer status = (Integer) map.get("status"); // 假设 status 是 TINYINT 映射为 Integer
            Long count = (Long) map.get("count");
            String name = (status != null && status == 1) ? "成功" : "失败"; // 简化处理，0 和 null 都算失败
            return new NameValueDTO(name, count != null ? count : 0L);
        }).collect(Collectors.toList());

        // 注意：这里只有成功/失败，前端模拟的更多状态需要后端支持
    }

    @Override
    public List<NameValueDTO> getTopApis(int limit, String period) {
        LocalDateTime start;
        LocalDateTime end = LocalDateTime.now();

        switch (period.toLowerCase()) {
            case "last7days":
                start = end.minusDays(7).with(LocalTime.MIN);
                break;
            case "today":
            default:
                start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
                break;
        }

        List<Map<String, Object>> topApiCounts = dashboardMapper.getTopCalledApisBetween(start, end, limit);

        // 转换为 NameValueDTO 列表 (需要查询 API 名称)
        return topApiCounts.stream().map(map -> {
            Long apiId = (Long) map.get("api_id");
            Long count = (Long) map.get("count");
            String apiName = "未知API"; // 默认值
            if (apiId != null) {
                try {
                    // 假设 ApiInfoMapper 有 selectApiInfoById 方法
                    // 考虑性能：如果 topApiCounts 很大，批量查询 API 名称更好
                    com.alax.interfaces.domain.ApiInfo apiInfo = apiInfoMapper.selectApiInfoById(apiId); // 假设 ApiInfo 存在
                    if (apiInfo != null && apiInfo.getName() != null) {
                        apiName = apiInfo.getName();
                    }
                } catch (Exception e) {
                    System.err.println("Error getting API name for ID " + apiId + ": " + e.getMessage());
                }
            }
            return new NameValueDTO(apiName, count != null ? count : 0L);
        }).collect(Collectors.toList());
    }

    @Override
    public RealtimeStatsDTO getRealtimeStats() {
        RealtimeStatsDTO stats = new RealtimeStatsDTO();
        
        try {
            // 获取实时统计数据
            List<Map<String, Object>> timePointsData = dashboardMapper.getRealtimeStats();
            List<TimePointStats> timePoints = new ArrayList<>();
            
            if (timePointsData != null) {
                for (Map<String, Object> data : timePointsData) {
                    TimePointStats point = new TimePointStats();
                    point.setTimePoint(String.valueOf(data.getOrDefault("time_point", "")));
                    point.setCallCount(((Number) data.getOrDefault("call_count", 0)).longValue());
                    point.setAvgResponseTime(new BigDecimal(String.valueOf(data.getOrDefault("avg_response_time", 0)))
                        .setScale(2, RoundingMode.HALF_UP));
                    point.setErrorCount(((Number) data.getOrDefault("error_count", 0)).longValue());
                    
                    // 计算错误率
                    if (point.getCallCount() > 0) {
                        point.setErrorRate(new BigDecimal(point.getErrorCount())
                            .divide(new BigDecimal(point.getCallCount()), 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal(100)));
                    } else {
                        point.setErrorRate(BigDecimal.ZERO);
                    }
                    
                    timePoints.add(point);
                }
            }
            
            stats.setTimePoints(timePoints);
            
            // 获取汇总数据
            Map<String, Object> summary = dashboardMapper.getRealtimeSummary();
            if (summary != null) {
                stats.setTotalCalls(((Number) summary.getOrDefault("total_calls", 0)).longValue());
                stats.setErrorCalls(((Number) summary.getOrDefault("error_calls", 0)).longValue());
                stats.setAvgResponseTime(new BigDecimal(String.valueOf(summary.getOrDefault("avg_response_time", 0)))
                    .setScale(2, RoundingMode.HALF_UP));
                stats.setActiveUsers(((Number) summary.getOrDefault("active_users", 0)).longValue());
                
                // 计算总错误率
                if (stats.getTotalCalls() > 0) {
                    stats.setErrorRate(new BigDecimal(stats.getErrorCalls())
                        .divide(new BigDecimal(stats.getTotalCalls()), 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal(100)));
                } else {
                    stats.setErrorRate(BigDecimal.ZERO);
                }
            }
        } catch (Exception e) {
            log.error("获取实时统计数据失败", e);
            // 返回空对象，避免NPE
            stats.setTimePoints(new ArrayList<>());
            stats.setTotalCalls(0L);
            stats.setErrorCalls(0L);
            stats.setAvgResponseTime(BigDecimal.ZERO);
            stats.setActiveUsers(0L);
            stats.setErrorRate(BigDecimal.ZERO);
        }
        
        return stats;
    }

    @Override
    public List<Map<String, Object>> getUserBehaviorStats(Long userId, String period) {
        try {
            LocalDateTime startTime = getStartTime(period);
            return dashboardMapper.getUserBehaviorStats(startTime, userId);
        } catch (Exception e) {
            log.error("获取用户行为统计失败", e);
            return new ArrayList<>();
        }
    }

    private LocalDateTime getStartTime(String period) {
        LocalDateTime now = LocalDateTime.now();
        switch (period.toLowerCase()) {
            case "hour":
                return now.minusHours(1);
            case "day":
                return now.with(LocalTime.MIN);
            case "week":
                return now.minusWeeks(1);
            case "month":
                return now.minusMonths(1);
            default:
                return now.with(LocalTime.MIN);
        }
    }
}